﻿#ifndef PST_LINECHARTWINDOW_H
#define PST_LINECHARTWINDOW_H

#include <QPair>
#include "Graph2DWindowBase.h"
#include "DataModelPost.h"
#include "CalculationFormulaFunction.h"
#include "InfomationCurve2DBasical.h"

class LineChartTracer;

namespace pst
{

    class LineChartCenterSettingData : public QObject
    {
    public:
        LineChartCenterSettingData(QObject* parent) : QObject(parent) {}

        LineChartCoordinateSettingData* m_lineChartCoordinateSettingData = nullptr;
        Style2D_DataProperty* m_style2D_DataProperty = nullptr;

    private:
        int m_windowID = -1;
    };

    class LineChartTracer;
    class LineChartStraightLine;
    class LineChartSidebarSettingsDialog;
    class LineChartCoordinateSettingData;
    class TracerTableWidget;
    class MeasureTableWidget;
    class PostEnumType;
    /// @brief 二维图形
    class LineChartWindow : public Graph2DWindowBase
    {
        Q_OBJECT
    public:
        explicit LineChartWindow(QWidget* parent, int windowId, QList<Info2DPointer>* infoListCopy);
        ~LineChartWindow();

        void adjustLegendColumns();

        /// @brief 文件写出至工程文件
        QDomElement& writeToProjectFile(QDomDocument* doc, QDomElement* element, bool isdiso = false) override;

        /// @brief 从工程文件读入数据
        void readFromProjectFile(QDomElement* element, bool isdiso = false) override;

        void setWindowID(int windowID) override;
        int getWindowID() const override;

        void setWindowUniversalID(int windowUniversalID) override;
        int getWindowUniversalID() const override;

        LineChartCenterSettingData* getLineChartCenterSettingData() { return m_centerSettingData; };

        void addGraph2D(Info2DPointer& info) override; // 传引用，改数据

        bool getIsEdit() const { return m_editAction; };
        void setIsEdit(bool f) { m_editAction = f; };

        bool GetXAutoFlag() const
        {
            return m_autoXRescaleAxes;
        }
        void SetXAutoFlag(bool autoXRescaleAxes)
        {
            m_autoXRescaleAxes = autoXRescaleAxes;
        }
        bool GetYAutoFlag() const
        {
            return m_autoYRescaleAxes;
        }
        void SetYAutoFlag(bool autoYRescaleAxes)
        {
            m_autoYRescaleAxes = autoYRescaleAxes;
        }
        QString GetUnit() const
        {
            return m_unit;
        }

        bool GetXTitleAutoFlag() const
        {
            return m_autoXTitleText;
        }
        void SetXTitleAutoFlag(bool autoXTitleText)
        {
            m_autoXTitleText = autoXTitleText;
        }
        bool GetYTitleAutoFlag() const
        {
            return m_autoYTitleText;
        }
        void SetYTitleAutoFlag(bool autoYTitleText)
        {
            m_autoYTitleText = autoYTitleText;
        }
        int getCustomRangePlotMaxIndex();

    signals:
        void signal_updateStandardCcurveState(bool state);
        void signal_infoListCopy(QList<Info2DPointer>* infoListCopy);
        void signal_infoListPaste();

    public slots:
        void slot_adaptiveRange() override;                                            // 自适应范围
        void slot_chosenItemsChanged(const QList<QStandardItem*>& itemList) override;  // 右侧栏选项更改响应
        void slot_LinePropertyShow(QCPGraph* plottable, int index);                    // 属性设置弹窗显示
        void slot_ChangeLineProperty(int windowUniversalID, int curveInfoID, Info2DPointer info = nullptr, bool bCheckName = true); // 属性弹窗设置修改//Info2DPointer info用于打开项目时配置曲线数据
        void slot_showHideItemActor(QStandardItem* item);                              // 右侧栏隐藏眼睛点击响应
        void slot_updateSelectedGraph();                                               // 更新选择曲线状态
        void slot_editSelectedGraph();                                                 // 编辑选择曲线
        void slot_removeSelectedGraph();                                               // 删除选择曲线
        void slot_removeGraphs(const QList<QCPGraph*>& graphList);                     // 删除曲线
        void slot_removeGraphs(const QList<QString>& graphNameList);                   // 删除曲线
        void slot_copySelectedGraph();                                                 // 复制选择曲线
        void slot_removeAlldGraph();                                                   // 删除所有曲线
        void slot_renameGraph();                                                       // 曲线重命名
        void slot_renameCheck();                                                       // 曲线重命名重名判断
        void slot_copyGraph();                                                         // 复制曲线
        void slot_checkCurveNameExist(QString curveName, bool &exist);
        void slot_AddTracer();                                                           // 添加标记
        void slot_ShowPreviewTracer(QMouseEvent* event);                                 // 预览标记移动处理
        void slot_removeSelectedTracer(const QList<LineChartTracer*>& selectTracers);    // 删除选择标记
        void slot_removeAllTracer(const QList<LineChartTracer*>& tracers);               // 删除所有标记
        void slot_TracerPropertyShow(LineChartTracer* tracer);                           // 标记属性设置窗口显示
        void slot_ChangeTracerProperty(int tracerID, int guideLineID);                   // 标记属性设置修改

        void slot_GuideLinePropertyShow(LineChartStraightLine* guideLine);            // 参考线属性设置窗口显示
        void slot_ChangeGuideLineProperty(int tracerID, int guideLineID);  // 参考线属性设置修改

        void slot_measureData(const QString& measureNama, double value = 0); // 测量数据
        void slot_measureData(MeasureType type, double value = 0);           // 测量数据
        void slot_smoothData(double range);                                  // 平滑计算
        //返回值 -1：类型不满足, 0：正常 1：单x轴对数插值不满足条件 2：单y轴对数插值不满足条件  3：双轴对数插值不满足条件
        int slot_interpolationData(int number, InterpolationType type);
        // 插值计算
        void slot_updateBeamBandwidthProperty();                             // 半功率波束带宽属性更新
        void slot_updateStandingWaveBandwidthProperty();                     // 驻波带宽属性更新

        void slot_getCurveNames(QStringList& names);                            // 获取当前所有曲线名（公式编辑使用）
        void slot_calculationCheck(const Info2DPointer& info, bool& isSuccess); // 公式编辑计算检测

        void slot_addStandardCcurve(Info2DPointer& info);                                                                                                                           // 添加标准曲线
        void slot_totalCalculation(const QStringList& xNameList, const QStringList& yNameList, const QStringList& zNameList);                                                       // 总量计算
        bool slot_computeHIRF(const QStringList& graphNameList, double incidentWaveFieldValue, TextFileParser* textFileParser, const QString& typeName, bool isCheckBoxChecked);                            // HIRF外推计算
        void slot_computeEffectiveness(const QStringList& graphNameList, double e0);                                                                                                // 屏蔽效能计算
        void slot_computeTransferFunction(const QString& graphName, const QString& calibrationGraphName, const QString& type);                                                      // 传递函数计算
        void slot_computeIPL(const QList<QVariant>& IPLDatas, bool* success);                                                                                                         // IPL计算
        bool slot_computeWaveformAnalysis(const QString& graphName, double cutOffFrequency, const QString& filterType, int filterOrder, double leftBoundary, double rightBoundary, int windowId, QString resultList, bool isPythonRun = false); // 波形分析计算
        void slot_submitEvaluation(int emulationType, const QStringList& graphNameList);                                                                                            // 提交评估

        void slot_updateName();               // 更新曲线名（在曲线名后加上【类型】）
        void slot_updateUnit();               // 更新x、y轴中【】内单位的显示
        void slot_updateSelectedGraphState(); // 更新选择曲线标志，适用于是否可测量
        void slot_checkStandardCcurveState(); // 更新标准曲线标志，适用于是否可添加标准曲线

        void slot_getSidebarCurveDataSource(QString& dataSource); // 获取数据来源

        void slot_autoGetXTitleText(QString& xTitleText); // 自动更新横轴显示文本
        void slot_autoGetYTitleText(QString& yTitleText); // 自动更新纵轴显示文本

        void slot_changeAllCurveVariableAxis(const QString& newVariableAxisName); // 所有曲线更改变量

        // 左侧关闭工程树，删除相应的图像
        //  注意items是左侧工程树的节点
        void slot_closeTree(const QList<QStandardItem*>& items);

        void slot_localScope(double rangeLower, double rangeUpper, const QList<QString>& selectNames, bool& execFlag, bool edit); // 局部范围

        void updateAxisRange();

    public: // Python
        void pyVariableAxisChanged(QList<int> allSelectedItemIndexList, int result, QString variableAxistCurrentText);
        void pyCurveNameClicked(QList<int> allSelectedItemIndexList);
        void pyFixedValueChanged(QList<int> allIndexList);
        void pyCurveNameCheckStateChanged(int index, int checkStatus);
        void pyDataOperationChanged(bool isNormChecked, bool isDBChecked, bool isMathOperationChecked);
        void pyDataOperationChanged(int currentIndex);
        void slot_lineChartSaveMainSettingData(int index,
                                               bool axiDisIsAutoName, QString axiDisTitleText, QString axiDisTitleFontColorStr, int axiDisTitleFontSize, QString axiDisAxisColorStr, int axiDisAxisThickness, double axiDisValuePrecision, QString axiDisAxisDigitColorStr, int axiDisAxisDigitSize,
                                               bool axiRangIsAutoRange, double axiRangMaxValue, double axiRangMinValue, bool axiRangIsAutoStepSize, double axiRangCustomStepSize,
                                               bool yAxiDisIsAutoName, QString yAxiDisTitleText, QString yAxiDisTitleFontColorStr, int yAxiDisTitleFontSize, QString yAxiDisAxisColorStr, int yAxiDisAxisThickness, double yAxiDisValuePrecision, QString yAxiDisAxisDigitColorStr, int yAxiDisAxisDigitSize,
                                               bool yAxiRangIsAutoRange, double yAxiRangMaxValue, double yAxiRangMinValue, bool yAxiRangIsAutoStepSize, double yAxiRangCustomStepSize,
                                               bool gridIsMainGridLineDisplay, QString gridMainGridLineColorStr, int gridMainGridLineStyle, double gridMainGridLineThickness, bool gridIsSecondaryGridLineDisplay, QString gridSecondaryGridLineColorStr, int gridSecondaryGridLineStyle, double gridSecondaryGridLineThickness,
                                               QString titleName, QString titleFontColorStr, int titleFontSize,
                                               QString legendFontColorStr, int legendFontSize, QString legendLineColorStr, int legendLineThickness,
                                               QString resultDataName, QString dataLineColorStr, int dataLineStyle, double dataLineThickness, bool isDisplaySymbol, int symbolStyle, double symbolSize, QString symbolColorStr);

        void pyShowWaveButterAndFFT(const QList<double>& yData);
        void pyAddTracer(QString parameters);

        void pySubmitEvaluation(int emulationType, QString parms);

    protected:
        void initConnections() override;
        void updateCurve(QStandardItem* item, Info2DPointer& info) override;
        bool eventFilter(QObject* watched, QEvent* event) override;

        QQueue<QString> AnalyzeFormulaString(QString& str);                                                                     // 分析公式字符串
        CalculationData Symbolics(const CalculationData& first, const CalculationData& second, const QString& computeOperator); // 符号计算
        CalculationData Formula(const QString& str, const CalculationData& selfData);                                           // 函数计算
        CalculationData compute(QQueue<QString> queue, const CalculationData& selfData);                                        // 计算输入的公式

        QStringList GetCurveNames();                                                             // 获取当前所有曲线名（公式编辑使用）
        CalculationData GetCurveData(const QString& curveName, const CalculationData& selfData); // 获取与当前计算曲线处理后的curveName曲线数据

        void addNewGraph(Info2DPointer& info, QString params = "", bool isAutoName = false); // 添加新曲线

        void addNewGraphByOpenProject(Info2DPointer& info, QString params, bool isAutoName = false); // 打开项目时添加曲线

        QList<CalculationData> GetCurveDataByNames(const QList<QString>& names); // 获取所有曲线处理后的相关曲线数据，所有曲线会处理整个大合集数据，交集部分会各自插值

        // 对某一条曲线的数据进行单位转换
        void doInfoUnitConversion(Info2DPointer& info);

    private:
        void linearInterpolationMethod(int number, QSharedPointer<QCPGraphDataContainer> graphData, QVector<double>& xData, QVector<double>& yData);                              // 线性插值方法
        bool logarithmicInterpolationMethod(int number, QSharedPointer<QCPGraphDataContainer> graphData, QVector<double>& xData, QVector<double>& yData, InterpolationType type); // 对数插值方法
        QList<LineChartTracer*> getAllTracers(QCustomPlot* customPlot);

        bool doUnitConversion(const Info2DPointer& info);
        bool doUnitConversion(const QString& oldUnit, const QString& newUnit, QList<double>& value);
        void initCoordinateSystem();
        bool getHasSameName(const QString& name); // 判断曲线名是否重复

        QString serializeTracer(QCPItemTracer* previewTracer, QCustomPlot* customPlot,
            QString markerName, int setCurveInfoID, int tracerIndex);
        void importTracerFromList(const QString& sl, QCustomPlot* customPlot, LineChartTracer* tracer);
        void hirfExtrapolationCurvesDataExport(const QString& typeName, const QString& newFileName, const Info2DPointer& info, int times);
        bool writeHirfExtrapolationDataToFile(QString fileName, QVector<QPair<QString, QVector<double>>> datas);

        void submitEvaluation(int emulationType, const QStringList& graphNameList, bool savePy);

    private:
        enum DataAnalysisType
        {
            HIRF = 0,
            Effectiveness,
            Lighting,
            TransferFunction,
            IPL,
            WaveformAnalysis,
            SmoothData,
            Interpolation,
            InterpolationSingleAxisX,
            InterpolationSingleAxisY,
            InterpolationDoubleAxis,
            LocalRange,
            Count
        };

    private:
        /// @brief 二维图形设置
        LineChartSidebarSettingsDialog* m_settings{nullptr};

        bool m_autoXRescaleAxes = true;
        bool m_autoYRescaleAxes = true;
        QCPRange m_xAxisRange;
        QCPRange m_yAxisRange;
        QCPAbstractPlottable* m_doubleClickPlottable = nullptr;
        LineChartTracer* m_doubleClickTracer = nullptr;
        LineChartStraightLine* m_doubleClickGuideLine = nullptr;
        int m_tracerIndex = 0;
        TracerTableWidget* m_tracerPropertyWidget;
        MeasureTableWidget* m_measureTableWidget;
        QString m_unit;
        QString m_yUnit;
        int m_graphIndex{0};
        int m_windowUniversalID{-1};
        int m_windowId{0};
        QHash<QString, int> m_standardCcurveNumber;
        int m_hirfNumber = 1;
        int m_effectivenessNumber = 1;

        bool m_autoXTitleText = true;
        bool m_autoYTitleText = true;
        // int m_xAxisUnitType = -1; //x轴数据类型
        // QString m_xAxisUnit = ""; //x轴数据单位

        // QList<QPair<int, QString>> m_yAxisUnitList;//存储多个结果类型的当前单位

        LineChartCenterSettingData* m_centerSettingData;
        LineChartCoordinateSettingData* m_coodinateSetting;

        Info2DPointer m_currentUsingWaveButterAndFFTInfo = nullptr;
        QString m_waveParams;
        QStandardItem* m_waveItem;

        int m_waveAnalysisId = 1;      // 波形分析编号
        int m_hirfExtrapolationId = 1; // hirf外推编号
        int m_computeTransferId = 1;   // 传递函数编号
        int m_IPLId = 1;               // IPL编号
        int m_interpolateId = 1;       // 插值
        int m_smoothId = 1;            // 平滑
        int m_localRangeId = 0;        //局部范围
        bool m_editAction = false;
        //目前项目保存功能未完善，所以暂时未保存局部范围序号当前最大值。项目保存功能完善后，记得加上m_customRangePlotMaxIndex保存和读取功能，保证项目打开后序号能够正常自增。
        int m_customRangePlotMaxIndex{1}; // 局部范围曲线序号，新生成的曲线命名方式为“原曲线名_局部范围序号_局部范围起点值_局部范围终点值”，序号从1开始，根据添加局部范围的次数依次递增，例如“曲线_1[Gain]_局部范围1_0_50”
        /*
         * 自增命名
         */
        QString LineChartWindow::autoIncrementName(QString text);

        bool m_execSuccessFlag;

        QHash<int, QString> getMarkerNameMap();
        QPair<QString, QVector<double>> m_tempValueData;//点电场峰值数据

    };
} // namespace pst

#endif // PST_LINECHARTWINDOW_H
